package com.meizi.experimentcode;

import com.meizi.experimentcode.appimpl.ApplePredicate;
import com.meizi.experimentcode.appimpl.ApplePredicateImpl;
import com.meizi.experimentcode.entity.Apple;
import com.meizi.experimentcode.entity.Dish;
import org.junit.jupiter.api.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @author Administration
 * @date 2022/2/24 - 9:46 - 星期四
 * @project lambda
 * @package com.meizi.experimentcode
 * @by 晨
 */
public class Testing {

    public List<Apple> appleList(){
        List<Apple> appleS = new ArrayList<>();
        Apple apple = new Apple();
        apple.setColor("red");
        apple.setWeight(130);
        appleS.add(apple);

        Supplier<Apple> appleSupplier = Apple::new;
        Apple apple1 = appleSupplier.get();
        apple1.setColor("yellow");
        apple1.setWeight(160);
        appleS.add(apple1);

        Supplier<Apple> appleSupplier1 = Apple::new;
        Apple apple2 = appleSupplier.get();
        apple2.setColor("geen");
        apple2.setWeight(260);
        appleS.add(apple2);
        return appleS;
    }

    public List<Apple> appleS(){
        List<Apple> appleS = new ArrayList<>();
        Apple apple = new Apple();
        apple.setColor("red");
        apple.setWeight(130);
        apple.setAge(30);
        appleS.add(apple);

        Supplier<Apple> appleSupplier = Apple::new;
        Apple apple1 = appleSupplier.get();
        apple1.setColor("yellow");
        apple1.setWeight(360);
        apple1.setAge(50);
        appleS.add(apple1);

        Supplier<Apple> appleSupplier1 = Apple::new;
        Apple apple2 = appleSupplier1.get();
        apple2.setColor("geen");
        apple2.setWeight(360);
        apple2.setAge(30);
        appleS.add(apple2);
        return appleS;
    }

    @Test
    public void aaaaaa () throws ParseException {
        System.out.println(List.class.getName());
        System.out.println(String.class.getName());
    }


    @Test
    public void aass () {
        List<Apple> apples = appleList();
        List<Apple> apples1 = appleS();

        List<Apple> collect = apples.stream().filter((x) -> apples1.stream().map(Apple::getWeight)
                .collect(Collectors.toList()).contains(x.getWeight())).collect(Collectors.toList());
        System.out.println(collect);
    }

   @Test
    public void a(){
       // 测试函数型接口
       List<Apple> predicate = predicate(appleList(), (Apple apple) -> apple.getWeight() > 150);
       System.out.println(predicate);
   }

    public static List<Apple> predicate(List<Apple> inventory, Predicate<Apple> p) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (p.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }


    @Test
    public void b () {
        List<Apple> apples = filterApples(appleList(), new ApplePredicateImpl());
        System.out.println(apples);
    }

    public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (p.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }

    @Test
    public void c () {
        List<Apple> apples = appleList();
        apples.sort(Comparator.comparing(Apple::getWeight).reversed());
        System.out.println(apples);
    }

    /*测试 predicate 断言型接口*/
    @Test
    public void d (){
        Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
        List<String> stringList = new ArrayList<>();
        stringList.add("");
        stringList.add("red");
        stringList.add("green");
        List<String> filter = filter(stringList, nonEmptyStringPredicate);
        System.out.println(filter);
    }

    public <T> List<T> filter (List<T> list, Predicate<T> p) {
        List<T> result = new ArrayList<>();
        for (T t : list) {
            if (p.test(t)) {
                result.add(t);
            }
        }
        return result;
    }

    /* 测试 consumer 消费型接口 */
    @Test
    public void e (){
        forEach(
                Arrays.asList("1","2"),
                (String i) -> System.out.println(i)
        );
        Supplier<Apple> appleSupplier = Apple::new;
        Apple apple = appleSupplier.get();

    }

    public <T> void forEach (List<T> list, Consumer<T> c) {
        for (T t : list) {
            c.accept(t);
        }
    }

    @Test
    public void f () {
        List<Apple> apples = this.appleList();
        List<String> collect = apples.stream()
                .filter((x) -> x.getWeight() > 150)
                .sorted(Comparator.comparing(Apple::getWeight).reversed())
                .map(Apple::getColor)
                .limit(3)
                .collect(Collectors.toList());
        System.out.println(collect);

    }

    // 测试 Stream
    public List<Dish> menuList(){
        List<Dish> a = Arrays.asList(
        new Dish("pork",false,800,Dish.Type.MEAT),
                new Dish ("beef",false,700,Dish.Type.MEAT),
                new Dish("chicken",false,400,Dish.Type.MEAT),
                new Dish("french fries",true,530,Dish.Type.OTHER),
                new Dish ("rice",true,350,Dish.Type.OTHER),
                new Dish("season fruit",true,120,Dish.Type.OTHER),
                new Dish("pizza",true,550,Dish.Type.OTHER),
                new Dish("prawns",false,300,Dish.Type.FISH),
                new Dish("pizza",false,450,Dish.Type.FISH));
        List<Dish> menu = new ArrayList<>(a);
        return menu;
    }

    @Test
    public void g () {
        List<Dish> dishes = menuList();
        List<String> collect = dishes.stream()
                .filter((x) -> {
                    System.out.println("filtering" + x.getName());
                    return x.getCalories() > 300;
                })
                .map((x) -> {
                    System.out.println("maping" + x.getName());
                    return x.getName();
                })
                .limit(3)
                .collect(Collectors.toList());

    }

    @Test
    public void h (){
        List<Integer> numbers1 = Arrays.asList(1, 2, 3);

        List<Integer> numbers2 = Arrays.asList(3,4);

        List<int[]> collect = numbers1.stream()
                .flatMap((i) -> numbers2.stream()
                        .map((j) -> new int[]{i, j}))
                .collect(Collectors.toList());
    }

    @Test
    public void l () {
        List<Dish> dishes = menuList();
        Integer num = 0;
        if (dishes.stream().anyMatch((x) -> x.getType().equals(Dish.Type.OTHER))){
            System.out.println(num);
            num++;
        }
    }

    @Test
    public void j () {
        List<Dish> dishes = menuList();
        dishes.stream()
                .filter((x) -> x.getCalories() > 60000)
                .findAny()
                .ifPresent((x) -> System.out.println(x));

    }

    // 规约
    @Test
    public void k () {
        List<Dish> dishes = menuList();
        Integer reduce = dishes.stream()
                .map(Dish::getCalories)
                .reduce(0, Integer::sum);
        System.out.println(reduce);

        Optional<Integer> reduce1 = dishes.stream()
                .map(Dish::getCalories)
                .reduce(Integer::max);
        System.out.println(reduce1);
    }

    @Test
    public void m () {
        Stream<double[]> stream = IntStream.rangeClosed(1, 100).boxed()
                .flatMap((a) ->
                        IntStream.rangeClosed(a, 100)
                                .mapToObj(
                                        (b) -> new double[]{a, b, Math.sqrt(a * a + b * b)})
                                .filter(t -> t[2] % 1 == 0));
        System.out.println(stream.collect(Collectors.toList()));
    }

    @Test
    public void n () {
        List<Dish> dishes = menuList();
        String collect = dishes.stream().map(Dish::getName).collect(Collectors.joining(","));
        System.out.println(collect);
    }

    @Test
    public void o () {
        List<Dish> dishes = menuList();
        Map<Dish.Type, Optional<Dish>> collect = dishes.stream()
                .collect(Collectors.groupingBy(Dish::getType, Collectors.maxBy(Comparator.comparingInt(Dish::getCalories))));
        System.out.println(collect);
    }

    @Test
    public void p () {
        List<Dish> dishes = menuList();
        Map<Dish.Type, Dish> collect = dishes.stream()
                .collect(Collectors.groupingBy(Dish::getType,
                        Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(Dish::getCalories)), Optional::get)));
        System.out.println(collect);
    }

    @Test
    public void q () {
        List<Dish> dishes = menuList();
        Map<Dish.Type, HashSet<String>> collect = dishes.stream()
                .collect(Collectors.groupingBy(Dish::getType,
                        Collectors.mapping((dish) -> {
                            if (dish.getCalories() <= 400) {
                                return dish.getName();
                            } else if (dish.getCalories() <= 700) {
                                return dish.getName();
                            } else {
                                return dish.getName();
                            }
                        }, Collectors.toCollection(HashSet::new))));
        System.out.println(collect);
    }

    @Test
    public void r () {
        List<Dish> dishes = menuList();
        Map<Boolean, List<Dish>> collect = dishes.stream()
                .collect(Collectors.partitioningBy(Dish::isVegetarian));
        System.out.println(collect);
    }


    @Test
    public void s () {
        Apple apple = new Apple();
        System.out.println("1号" + apple);
        Optional<Apple> apple1 = Optional.ofNullable(apple);
        apple1.ifPresent((x) -> System.out.println("不知道" + x.getColor()));

        StringBuilder sb = new StringBuilder();
        String ln = "\r\n";
        sb.append("12345").append(ln).append("23456").append("23456" );
        System.out.println(sb.toString());
    }

    @Test
    public void t () {
        LocalDate date1 = LocalDate.of(2017, 9, 21);
        LocalDate date2 = date1.withYear(2011);
        System.out.println(date2);
        LocalDate date3 = date2.withDayOfMonth(25);
        System.out.println(date3);
        LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 2);
        System.out.println(date4);
    }

    @Test
    public void u () {
        List<Dish> dishes = menuList();
        System.out.println(dishes);
        ArrayList<Dish> collect = dishes.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing(Dish::getName))), ArrayList::new));
        System.out.println(collect);
    }


    @Test
    public void v () {
        // 获取获取本月第一天0点时间
        Calendar firstDay = Calendar.getInstance();
        firstDay.set(firstDay.get(Calendar.YEAR), firstDay.get(Calendar.MONTH), firstDay.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        firstDay.set(Calendar.DAY_OF_MONTH, firstDay.getActualMinimum(Calendar.DAY_OF_MONTH));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String firstDayFormat = sdf.format(firstDay.getTime());
        System.out.println(firstDayFormat);
        // 获得本月最后一天24点时间
        Calendar TheLastDay = Calendar.getInstance();
        TheLastDay.set(TheLastDay.get(Calendar.YEAR), TheLastDay.get(Calendar.MONTH), TheLastDay.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        TheLastDay.set(Calendar.DAY_OF_MONTH, TheLastDay.getActualMaximum(Calendar.DAY_OF_MONTH));
        TheLastDay.set(Calendar.HOUR_OF_DAY, 24);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String theLastDayFormatDate = simpleDateFormat.format(TheLastDay.getTime());
        System.out.println(theLastDayFormatDate);
    }

    @Test
    public void w () {
        LocalDateTime localTime=LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
        System.out.println(dateTimeFormatter.format(localTime));
        LocalDateTime localDateTime1 = localTime.plusDays(5L);
        System.out.println("增加5天后得时间" + dateTimeFormatter.format(localDateTime1));

        // date转换 localdatetime
        Date date = new Date();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = date.toInstant().atZone(zoneId).toLocalDateTime();
        System.out.println(dateTimeFormatter.format(localDateTime));

        LocalDateTime of = LocalDateTime.of(2017, 9, 21, 6, 30, 45);
        System.out.println(of.isBefore(localTime));
    }

    @Test
    public void x (){

        LocalDate date = LocalDate.now();
        LocalDate lastMonth = date.minusMonths(1); // 当前月份减1
        LocalDate firstDay = lastMonth.with(TemporalAdjusters.firstDayOfMonth()); // 获取当前月的第一天
        LocalTime of = LocalTime.of(0, 0, 0);
        LocalDateTime localDateTime = LocalDateTime.of(firstDay, of);

        LocalDate lastDay = lastMonth.with(TemporalAdjusters.lastDayOfMonth()); // 获取当前月的最后一天.
        LocalTime of1 = LocalTime.of(0, 0, 0);
        LocalDateTime localDateTime1 = LocalDateTime.of(lastDay, of1);

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
        System.out.println(dateTimeFormatter.format(localDateTime));
        System.out.println(dateTimeFormatter.format(localDateTime1));

    }

    @Test
    public void y () {
        // 获取上个自然月开始时间
        LocalDate date = LocalDate.now();
        // 当前月份减1
        LocalDate lastMonth = date.minusMonths(1);
        LocalDateTime firstLocalDateTime = this.first(lastMonth);
        // 结束时间
        LocalDateTime lastLocalDateTime = this.last(lastMonth);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
        String format = dateTimeFormatter.format(firstLocalDateTime);
        String format1 = dateTimeFormatter.format(lastLocalDateTime);
        System.out.println(format);
        System.out.println(format1);
    }

    private LocalDateTime first(LocalDate lastMonth) {
        // 获取当前月的第一天
        LocalDate firstDay = lastMonth.with(TemporalAdjusters.firstDayOfMonth());
        LocalTime of = LocalTime.of(0, 0, 0);
        LocalDateTime firstlocalDateTime = LocalDateTime.of(firstDay, of);
        return firstlocalDateTime;
    }

    private LocalDateTime last(LocalDate lastMonth) {
        // 获取当前月的最后一天.
        LocalDate lastDay = lastMonth.with(TemporalAdjusters.lastDayOfMonth());
        LocalTime of1 = LocalTime.of(23, 59, 59);
        LocalDateTime localDateTime1 = LocalDateTime.of(lastDay, of1);
        return localDateTime1;
    }
}
